require_relative 'player.rb'
require_relative 'hand.rb'
require_relative 'deck.rb'
require_relative 'pile.rb'
require_relative 'report'
require_relative 'plain_report'
require_relative 'report_base.rb'
require_relative 'html_report'
require_relative 'xml_report'
require_relative 'rdf_report'
require_relative 'observer_analyzer'
require_relative 'observer_officer'
require_relative 'poker_subject'

# Class that represents a simulation of simple 1-card poker game.
class Poker
  attr_reader :winning_cards, :players, :no_of_rounds, :table_no
  include PokerSubject

  # Create poker game of given number of rounds using players array.
  def initialize  no_of_rounds, players, table_no
    super()
    @players = players
    @no_of_rounds = no_of_rounds
    @table_no = table_no
    @results = Hash.new
    @players.each do |player|
      @results[player.name] = []
    end
    @report = nil
    @winning_cards = []


  end

  # Player the game of Poker.
  def play

    @pile = Pile.new
    @observer_officer = ObserverOfficer.new
    @pile.add_observer do |ref|
      @observer_officer.update ref
    end
    notify_game_observers self
    @no_of_rounds.times do
      play_round
      @pile.empty!
    end
  end

  # Play an individual round.
  def play_round
    @deck = Deck.new
    # deal each player a hand
    @players.each do |player|
      player.set_hand(@deck.deal_hand(1))
    end
    # Each player plays a card
    @players.each do |player|
      @pile.add(player.play)
    end
    winning_card = @pile.calculate_winner
    # find out who played the winning card
    winner = nil
    @players.each do |player|
      if winning_card == player.last_card_played
        winner = player
      end
    end
    @results[winner.name] << winning_card.to_s
    # notify observers when logic is clear who has winning card and information is already stored
    @winning_cards << winning_card.to_s
    notify_poker_observers self
    #notify_pile_observers self
  end

  # Print the overall results of the series of rounds
  def print_results
    @results.each do |name, results|
      puts "#{name} won #{@results[name].length} times with these cards: #{results}"
    end
  end

  def generate_report flag
    report_base = Report_Base.new(@players, @no_of_rounds, @results, @deck)
    if @report.nil? || !@report.is_a?(flag)
      @report = flag.new (report_base)
    end
      @report.generate_report
  end

  def is_report_init?
    if @report.nil?
      return false
    else
      return true
    end
  end

  def notify_game_observers ref
    @pile.notify_observers ref
  end

  def notify_poker_observers ref
    self.notify_observers ref
  end
end

